package com.ruoyi.generator.service.impl;

import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.text.CharsetKit;
import com.ruoyi.common.enums.HtmlPageTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.generator.domain.model.FileGenInfo;
import com.ruoyi.generator.service.IGenHtmlService;
import com.ruoyi.generator.service.IPrepareHtmlDataService;
import com.ruoyi.generator.service.PrepareHtmlDataHelper;
import com.ruoyi.generator.util.VelocityInitializer;
import org.apache.commons.io.FileUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.List;

@Service
public class GenHtmlServiceImpl implements IGenHtmlService {

    private static final Logger log = LoggerFactory.getLogger(GenHtmlServiceImpl.class);

    @Autowired
    private PrepareHtmlDataHelper prepareHtmlDataHelper;

    @Override
    public void generatorHTMLCode(FileGenInfo fileGenInfo) {
        StopWatch watch = new StopWatch();
        watch.start("generatorHTMLCode");
        log.info("生成页面开始,fileGenInfo:{}", fileGenInfo);
        String pageType = fileGenInfo.getPageType();
        HtmlPageTypeEnum pageTypeEnum = HtmlPageTypeEnum.getByValue(pageType);
        if (StringUtils.isNull(pageTypeEnum)) {
            throw new ServiceException(StringUtils.format("渲染模板失败,没有找到对应的页面类型:{}", pageType));
        }
        IPrepareHtmlDataService prepareHtmlDataService = prepareHtmlDataHelper.getPrepareHtmlDataService(pageType);
        if (StringUtils.isNull(prepareHtmlDataService)) {
            throw new ServiceException(StringUtils.format("渲染模板失败,对应的渲染方法未实现,页面类型:{}", pageType));
        }
        String businessId = fileGenInfo.getBusinessId();

        if (prepareHtmlDataService.useBusinessId()) {
            if (StringUtils.isNotEmpty(businessId)) {
                generatorWithBusinessId(pageTypeEnum, businessId);
            } else {
                List<String> allBusinessIds = prepareHtmlDataService.getAllBusinessIds();
                for (String bid : allBusinessIds) {
                    generatorWithBusinessId(pageTypeEnum, bid);
                }
            }
        } else {
            generatorWithoutBusinessId(pageTypeEnum);
        }
        watch.stop();
        log.info("生成页面结束,fileGenInfo:{},耗时:{}毫秒", fileGenInfo, watch.getTotalTimeMillis());
    }


    private void generatorWithBusinessId(HtmlPageTypeEnum pageTypeEnum, String businessId) {
        IPrepareHtmlDataService prepareHtmlDataService = prepareHtmlDataHelper.getPrepareHtmlDataService(pageTypeEnum.getValue());
        FileGenInfo fileGenInfo = new FileGenInfo();
        fileGenInfo.setBusinessId(businessId);
        String path = StringUtils.format(RuoYiConfig.getHtmlGenPath() + pageTypeEnum.getGenHtmlPath(), businessId);
        if (prepareHtmlDataService.usePage()) {
            generatorWithPage(pageTypeEnum, fileGenInfo, path);
        } else {
            generatorWithoutPage(pageTypeEnum, fileGenInfo, path);
        }
    }

    private void generatorWithoutBusinessId(HtmlPageTypeEnum pageTypeEnum) {
        IPrepareHtmlDataService prepareHtmlDataService = prepareHtmlDataHelper.getPrepareHtmlDataService(pageTypeEnum.getValue());
        FileGenInfo fileGenInfo = new FileGenInfo();
        String path = RuoYiConfig.getHtmlGenPath() + pageTypeEnum.getGenHtmlPath();
        if (prepareHtmlDataService.usePage()) {
            generatorWithPage(pageTypeEnum, fileGenInfo, path);
        } else {
            generatorWithoutPage(pageTypeEnum, fileGenInfo, path);
        }
    }

    private void generatorWithPage(HtmlPageTypeEnum pageTypeEnum, FileGenInfo fileGenInfo, String path) {
        IPrepareHtmlDataService prepareHtmlDataService = prepareHtmlDataHelper.getPrepareHtmlDataService(pageTypeEnum.getValue());
        VelocityInitializer.initVelocity();
        try {
            List<VelocityContext> velocityContexts = prepareHtmlDataService.prepareContextList(fileGenInfo);
            int page = 1;
            for (VelocityContext context : velocityContexts) {
                // 渲染模板
                StringWriter sw = new StringWriter();
                Template tpl = Velocity.getTemplate(pageTypeEnum.getVmFileName(), Constants.UTF8);
                tpl.merge(context, sw);
                try {
                    String pagePath;
                    if (page == 1) {
                        pagePath = StringUtils.format(path, "index.html");
                    } else {
                        pagePath = StringUtils.format(path, "p/" + page + "/index.html");
                    }
                    page++;
                    FileUtils.writeStringToFile(new File(pagePath), sw.toString(), CharsetKit.UTF_8);
                } catch (IOException e) {
                    throw new ServiceException("渲染模板失败，fileGenInfo：" + fileGenInfo);
                }
            }
        } catch (Exception e) {
            log.error("渲染模板失败,prepareHtmlDataService.prepareContextList异常,fileGenInfo:{}", fileGenInfo, e);
        }
    }

    private void generatorWithoutPage(HtmlPageTypeEnum pageTypeEnum, FileGenInfo fileGenInfo, String path) {
        IPrepareHtmlDataService prepareHtmlDataService = prepareHtmlDataHelper.getPrepareHtmlDataService(pageTypeEnum.getValue());
        VelocityInitializer.initVelocity();
        try {
            VelocityContext context = prepareHtmlDataService.prepareContext(fileGenInfo);
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(pageTypeEnum.getVmFileName(), Constants.UTF8);
            tpl.merge(context, sw);
            try {
                FileUtils.writeStringToFile(new File(path + "/index.html"), sw.toString(), CharsetKit.UTF_8);
            } catch (IOException e) {
                throw new ServiceException("渲染模板失败，fileGenInfo：" + fileGenInfo);
            }
        } catch (Exception e) {
            log.error("渲染模板失败,prepareHtmlDataService.prepareContext异常,fileGenInfo:{}", fileGenInfo, e);
        }
    }
}
